use crate::database::Database;
use log::{Level, Log, Metadata, Record};
use std::sync::{Arc, Mutex};

/// 自定义日志写入器，将日志写入数据库
pub struct DatabaseLogger {
    database: Arc<Mutex<Database>>,
}

impl DatabaseLogger {
    pub fn new(database: Arc<Mutex<Database>>) -> Self {
        Self { database }
    }

    pub fn init(database: Arc<Mutex<Database>>) -> Result<(), log::SetLoggerError> {
        let logger = Box::new(DatabaseLogger::new(database));
        log::set_boxed_logger(logger)?;
        log::set_max_level(log::LevelFilter::Debug);
        Ok(())
    }
}

impl Log for DatabaseLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= Level::Debug
    }

    fn log(&self, record: &Record) {
        if self.enabled(record.metadata()) {
            let level = match record.level() {
                Level::Error => "ERROR",
                Level::Warn => "WARN", 
                Level::Info => "INFO",
                Level::Debug => "DEBUG",
                Level::Trace => "DEBUG", // 将 TRACE 映射到 DEBUG
            };

            let message = format!("{}", record.args());
            let component = record.module_path();

            // 尝试写入数据库，如果失败则忽略（避免日志循环）
            if let Ok(db) = self.database.lock() {
                let _ = db.add_log(level, &message, component);
            }
        }
    }

    fn flush(&self) {
        // 数据库写入是同步的，不需要额外的刷新操作
    }
}

/// 组合日志写入器，同时写入控制台和数据库
pub struct CombinedLogger {
    console_logger: env_logger::Logger,
    database_logger: DatabaseLogger,
}

impl CombinedLogger {
    pub fn new(database: Arc<Mutex<Database>>) -> Self {
        let console_logger = env_logger::Builder::from_default_env()
            .filter_level(log::LevelFilter::Debug)
            .build();
        
        let database_logger = DatabaseLogger::new(database);
        
        Self {
            console_logger,
            database_logger,
        }
    }

    pub fn init(database: Arc<Mutex<Database>>) -> Result<(), log::SetLoggerError> {
        let logger = Box::new(CombinedLogger::new(database));
        log::set_boxed_logger(logger)?;
        log::set_max_level(log::LevelFilter::Debug);
        Ok(())
    }
}

impl Log for CombinedLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        self.console_logger.enabled(metadata) || self.database_logger.enabled(metadata)
    }

    fn log(&self, record: &Record) {
        // 写入控制台
        self.console_logger.log(record);
        
        // 写入数据库
        self.database_logger.log(record);
    }

    fn flush(&self) {
        self.console_logger.flush();
        self.database_logger.flush();
    }
}
